home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / rpc / rpcHistogram.c < prev    next >
C/C++ Source or Header  |  1990-10-02  |  7KB  |  268 lines

  1. /*
  2.  * rpcHistogram.c --
  3.  *
  4.  *      Simple histograms of event durations are maintained by the
  5.  *      routines in this module.  The data recorded includes an average of
  6.  *      time samples, and a histogram at some granularity of time
  7.  *      intervals.
  8.  *
  9.  * Copyright (C) 1986 Regents of the University of California
  10.  * All rights reserved.
  11.  */
  12.  
  13. #ifndef lint
  14. static char rcsid[] = "$Header: /sprite/src/kernel/rpc/RCS/rpcHistogram.c,v 9.1 90/10/02 16:29:31 mgbaker Exp $ SPRITE (Berkeley)";
  15. #endif /* not lint */
  16.  
  17.  
  18. #include <sprite.h>
  19. #include <stdio.h>
  20. #include <bstring.h>
  21. #include <status.h>
  22. #include <sync.h>
  23. #include <timer.h>
  24. #include <rpcHistogram.h>
  25. #include <stdlib.h>
  26. #include <vm.h>
  27.  
  28. #define LOCKPTR (&histPtr->lock)
  29.  
  30.  
  31. /*
  32.  *----------------------------------------------------------------------
  33.  *
  34.  * Rpc_HistInit --
  35.  *
  36.  *    Initialize the data structure used to keep an empirical time
  37.  *    distribution, or histogram.
  38.  *
  39.  * Results:
  40.  *    A pointer to the data structure, suitable for passing to
  41.  *    Rpc_HistStart and Rpc_HistStop.
  42.  *
  43.  * Side effects:
  44.  *    Allocates memory for the structure.
  45.  *
  46.  *----------------------------------------------------------------------
  47.  */
  48. Rpc_Histogram *
  49. Rpc_HistInit(numBuckets, usecPerBucket)
  50.     int numBuckets;    /* The number of columns in the histogram */
  51.     int usecPerBucket;    /* The time step between columns in the histogram */
  52. {
  53.     register Rpc_Histogram *histPtr;
  54.     register int bound;
  55.     Timer_Ticks startTicks, endTicks;
  56.  
  57.     histPtr = (Rpc_Histogram *)malloc(sizeof(Rpc_Histogram));
  58.     histPtr->numBuckets = numBuckets;
  59.     histPtr->bucket = (int *)malloc(numBuckets * sizeof(int));
  60.     Sync_LockInitDynamic(&histPtr->lock, "Rpc:histPtr->lock");
  61.     histPtr->aveTimePerCall.seconds = 0;
  62.     histPtr->aveTimePerCall.microseconds = 0;
  63.     bzero((Address)&histPtr->totalTime, sizeof(Time));
  64.     histPtr->numCalls = 0;
  65.     /*
  66.      * Truncate the usecPerBucket to a power of two.  This lets the sampling
  67.      * routines use shifts instead of modulo.
  68.      */
  69.     if (usecPerBucket < 2) {
  70.     usecPerBucket = 2;
  71.     }
  72.     histPtr->bucketShift = 0;
  73.     for (bound = 2 ; bound <= usecPerBucket ; bound <<= 1) {
  74.     histPtr->bucketShift++;
  75.     }
  76.     
  77.     histPtr->usecPerBucket = bound >> 1;
  78.     /*
  79.      * Time the cost of calling the histogram sampling routines.
  80.      */
  81.     Timer_GetCurrentTicks(&startTicks);
  82.     for (bound=0 ; bound<10 ; bound++) {
  83.     Time time;
  84.     Rpc_HistStart(histPtr, &time);
  85.     Rpc_HistEnd(histPtr, &time);
  86.     }
  87.     Timer_GetCurrentTicks(&endTicks);
  88.     Timer_SubtractTicks(endTicks, startTicks, &endTicks);
  89.     Timer_TicksToTime(endTicks, &histPtr->overheadTime);
  90.     Time_Divide(histPtr->overheadTime, 10, &histPtr->overheadTime);
  91.     Rpc_HistReset(histPtr);
  92.     return(histPtr);
  93. }
  94.  
  95. /*
  96.  *----------------------------------------------------------------------
  97.  *
  98.  * Rpc_HistReset --
  99.  *
  100.  *    Reset the histograms, so they start fresh for another benchmark.
  101.  *
  102.  * Results:
  103.  *    None.
  104.  *
  105.  * Side effects:
  106.  *    The counters and average are reset.
  107.  *
  108.  *----------------------------------------------------------------------
  109.  */
  110. ENTRY void
  111. Rpc_HistReset(histPtr)
  112.     register Rpc_Histogram *histPtr;
  113. {
  114.     register int i;
  115.  
  116.     LOCK_MONITOR;
  117.  
  118.     histPtr->numCalls = 0;
  119.     bzero((Address)&histPtr->totalTime, sizeof(Timer_Ticks));
  120.     histPtr->aveTimePerCall.seconds = 0;
  121.     histPtr->aveTimePerCall.microseconds = 0;
  122.     histPtr->numHighValues = 0;
  123.     for (i=0 ; i<histPtr->numBuckets ; i++) {
  124.     histPtr->bucket[i] = 0;
  125.     }
  126.  
  127.     UNLOCK_MONITOR;
  128. }
  129.  
  130. /*
  131.  *----------------------------------------------------------------------
  132.  *
  133.  * Rpc_HistStart --
  134.  *
  135.  *    Take a time sample to start a measured interval and update
  136.  *    the number of calls.  On a Sun-2 this costs about 650 microseconds.
  137.  *
  138.  * Results:
  139.  *    None.
  140.  *
  141.  * Side effects:
  142.  *    Take a time sample and count calls.
  143.  *
  144.  *----------------------------------------------------------------------
  145.  */
  146. ENTRY void
  147. Rpc_HistStart(histPtr, timePtr)
  148.     register Rpc_Histogram *histPtr;    /* The histogram */
  149.     register Time *timePtr;        /* Client storage area fro the time
  150.                      * sample */
  151. {
  152.     LOCK_MONITOR;
  153.     Timer_GetRealTimeOfDay(timePtr, (int *)NIL, (Boolean *)NIL);
  154.     histPtr->numCalls++;
  155.     UNLOCK_MONITOR;
  156. }
  157.  
  158. /*
  159.  *----------------------------------------------------------------------
  160.  *
  161.  * Rpc_HistEnd --
  162.  *
  163.  *    Called at the end of an interval, this determines the length of
  164.  *    the interval, keeps a running sum, and updates a counter
  165.  *    in the histogram corresponding to the interval length.
  166.  *
  167.  * Results:
  168.  *    None.
  169.  *
  170.  * Side effects:
  171.  *    Increment a counter in the histogram.
  172.  *
  173.  *----------------------------------------------------------------------
  174.  */
  175. ENTRY void
  176. Rpc_HistEnd(histPtr, timePtr)
  177.     register Rpc_Histogram *histPtr;    /* The histogram */
  178.     register Time *timePtr;        /* Result from Rpc_HistStart */
  179. {
  180.     Time endTime;
  181.     register int index;
  182.     LOCK_MONITOR;
  183.     Timer_GetRealTimeOfDay(&endTime, (int *)NIL, (Boolean *)NIL);
  184.     Time_Subtract(endTime, *timePtr, timePtr);
  185.     index = (timePtr->seconds * 1000 + timePtr->microseconds) >>
  186.         histPtr->bucketShift;
  187.     if (index >= histPtr->numBuckets) {
  188.     histPtr->numHighValues++;
  189.     } else {
  190.     histPtr->bucket[index]++;
  191.     }
  192.     Time_Add(histPtr->totalTime, *timePtr, &histPtr->totalTime);
  193.     UNLOCK_MONITOR;
  194. }
  195.  
  196. /*
  197.  *----------------------------------------------------------------------
  198.  *
  199.  * Rpc_HistDump --
  200.  *
  201.  *    Copy the histogram data structure to the callers buffer.
  202.  *    It is assumed that it is a user space buffer, and that it
  203.  *    is large enough (a lame assumption).
  204.  *
  205.  * Results:
  206.  *    None.
  207.  *
  208.  * Side effects:
  209.  *    The copy.
  210.  *
  211.  *----------------------------------------------------------------------
  212.  */
  213. ENTRY ReturnStatus
  214. Rpc_HistDump(histPtr, buffer)
  215.     register Rpc_Histogram *histPtr;
  216.     register Address buffer;
  217. {
  218.     register ReturnStatus status;
  219.     
  220.     LOCK_MONITOR;
  221.     status = Vm_CopyOut(sizeof(Rpc_Histogram), (Address)histPtr, buffer);
  222.     if (status == SUCCESS) {
  223.     buffer += sizeof(Rpc_Histogram);
  224.     status = Vm_CopyOut(histPtr->numBuckets * sizeof(int),
  225.                 (Address)histPtr->bucket, buffer);
  226.     }
  227.     UNLOCK_MONITOR;
  228.     return(status);
  229. }
  230.  
  231. /*
  232.  *----------------------------------------------------------------------
  233.  *
  234.  * Rpc_HistPrint --
  235.  *
  236.  *    Print the histogram data structure to the console.
  237.  *
  238.  * Results:
  239.  *    None.
  240.  *
  241.  * Side effects:
  242.  *    The copy.
  243.  *
  244.  *----------------------------------------------------------------------
  245.  */
  246. ENTRY void
  247. Rpc_HistPrint(histPtr)
  248.     register Rpc_Histogram *histPtr;
  249. {
  250.     register int i;
  251.     LOCK_MONITOR;
  252.     Time_Divide(histPtr->totalTime, histPtr->numCalls,
  253.                     &histPtr->aveTimePerCall);
  254.     printf("%d Calls,  ave %d.%06d secs each\n",
  255.            histPtr->numCalls, histPtr->aveTimePerCall.seconds,
  256.            histPtr->aveTimePerCall.microseconds);
  257.     for (i=0 ; i<histPtr->numBuckets ; i++) {
  258.     printf("%8d ", i * histPtr->usecPerBucket);
  259.     }
  260.     printf("Overflow\n");
  261.     for (i=0 ; i<histPtr->numBuckets ; i++) {
  262.     printf("%7d  ", histPtr->bucket[i]);
  263.     }
  264.     printf("%d\n", histPtr->numHighValues);
  265.     printf("\n");
  266.     UNLOCK_MONITOR;
  267. }
  268.